﻿#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
/*占位符：
	printf()可以在输出⽂本中指定占位符。
	所谓“占位符”，就是这个位置可以⽤其他值代⼊。*/
	printf("there are 3 apples\n");
	printf("there are %d apples\n", 3);
	printf("there are %d apples\n", 10);
	printf("\n");

	printf("zhangsan will come tonight\n");
	printf("%s will come tonight\n", "lisi");
	printf("%s will come tonight\n", "cuihua");
	printf("\n");

//多个占位符的情况
	printf("lisi says: it is 10 o'clock\n");
	printf("%s says: it is %d o'clock\n","ruhua",20);
	printf("\n");
	/*printf()参数与占位符是一一对应关系，如果有n个占位符，printf()的参数就应该有n+1个。
	如果参数个数少于对应的占位符，printf()可能会输出内存中的任意值。*/

//常见占位符列举：
	//%c：字符。//char
	//%d：⼗进制整数。//int
	//%f：⼩数（包含 float 类型和 double 类型）。
	//%hd：⼗进制 short int 类型。
	//%hu： unsigned short int 类型。
	//%ld：⼗进制 long int 类型。
	//%lu： unsigned long int 类型。
	//%lld：⼗进制 long long int 类型。
	//%llu： unsigned long long int 类型。
	//%Lf： long double 类型浮点数。
	//%o：⼋进制整数。
	//%p：指针（⽤来打印地址）。
	//%s：字符串。
	//%u：⽆符号整数（unsigned int）。
	//%x：⼗六进制整数。
	//%zd：size_t类型。
	//%% ：输出⼀个百分号。

//限定⼩数位数：
	//希望⼩数点后⾯只保留两位，占位符可以写成%.2f。
	printf("%f\n", 123.456);
	printf("%.3f\n", 123.456);
	printf("\n");

//这种写法可以与限定宽度占位符，结合使⽤。
	printf("%f\n", 0.5);
	printf("%6.2f\n", 0.5);//  0.50
	printf("\n");
	//%6.2f表⽰输出字符串最⼩宽度为6，⼩数位数为2。所以，输出字符串的头部有两个空格。

//最⼩宽度和⼩数位数这两个限定值，都可以⽤ * 代替，通过printf()的参数传⼊。
	printf("%*.*f\n", 6, 2, 0.5); //等同于printf("%6.2f\n", 0.5); 
	printf("\n");

//输出部分字符串
	//%s占位符⽤来输出字符串，默认是全部输出。
	//如果只想输出开头的部分，可以⽤% .[m]s指定输出的⻓度，
	//其中[m]代表⼀个数字，表⽰所要输出的⻓度。
	printf("%s\n", "abcdef");
	printf("%.3s\n", "abcdef");
	printf("\n");

//scanf
	//当我们有了变量，我们需要给变量输⼊值就可以使⽤ scanf 函数，
	//如果需要将变量的值输出在屏幕上的时候可以使⽤ prinf 函数。
	//int score = 0;
	//printf("请输入成绩:"); //输入一个整数，到score变量中
	//scanf("%d", &score); //& - 取地址操作符，&score 取出score变量的地址
	//printf("成绩是：%d\n", score);
	//printf("\n");

//输入读入多个变量
	//int i = 0;
	//int j = 0;
	//float x = 0.0;
	//float y = 0.0;
	//scanf("%d%d%f%f", &i, &j, &x, &y); 
	//printf("%d %d %f %f", i, j, x, y); 
	// scanf() 处理数值占位符时，会⾃动过滤空⽩字符，包括空格、制表符、换⾏符等。
	//所以，⽤户输⼊的数据之间，有⼀个或多个空格不影响 scanf() 解读数据。
	//另外，⽤户使⽤回⻋键，将输⼊分成⼏⾏，也不影响解读。

	//int x = 0;
	//float y = 0.0;
	//// ⽤⼾输入"   -13.45e6# 0" 
	//scanf("%d", &x); //13
	//printf("%d\n", x);
	//scanf("%f", &y); //.45e6(科学计数法的浮点数格式)-->0.45*10^6
	//printf("%f\n", y);
	//解读⽤户输入时，会从上⼀次解读遗留的第⼀个字符开始，
	//直到“读完缓存”，或者“遇到第⼀个不符合条件的字符”为⽌。
	//上⾯⽰例中, scanf() 读取⽤户输入时，%d占位符会忽略起⾸的空格，从 - 处开始获取数据，
	//读取到-13停下来，因为后⾯的.不属于整数的有效字符。这就是说，占位符%d只会读到-13就终止。
	//第⼆次调⽤ scanf() 时，就会从上⼀次停⽌解读的地⽅，继续往下读取。
	//这⼀次读取的⾸字符是 . ，由于对应的占位符是%f，会读取到 .45e12 。
	//后⾯的 # 不属于浮点数的有效字符，所以会停在这⾥。

//scanf的返回值
	//scanf() 的“返回值”是⼀个整数，表⽰“成功读取的变量个数”。
	//如果“没有读取任何项”，或者“匹配失败”，则返回 0 。
	//int a = 0;
    //int b = 0;
    //int c = 0;
    //int r = scanf("%d %d %d", &a, &b, &c);
    //printf("r = %d\n", r);
    //printf("a = %d b = %d c = %d\n", a, b, c);

	//int a = 0;
	//int b = 0;
	//while (scanf("%d%d", &a, &b) != EOF) //用于多组数据的输入
	////如果在成功读取任何数据之前，发⽣了读取错误或者遇到读取到⽂件结尾，则返回常量EOF(-1)。
	////在VS环境中需要按“对应变量个数”次 ctrl + z ，才结束了输入。
	////如果⼀个数字都不输入，直接按2次 ctrl + z, 输出的是 - 1，也就是EOF。
	////即若要终止这个while循环就需要连续输入2次 ctrl + z。
	//{
	//	printf("%d\n", a + b);
	//}

//scanf()占位符
	//scanf()常⽤的占位符如下，与 printf() 的占位符基本⼀致。
	//%c：字符。
	//%d：整数。
	//%f： float 类型浮点数。
	//%lf： double 类型浮点数。
	//%Lf： long double 类型浮点数。
	//%s：字符串。
	//%[]：在⽅括号中指定⼀组匹配的字符（⽐如% [0 - 9] ），遇到不在集合之中的字符，匹配将会停⽌。

//上⾯所有占位符之中，除了%c以外，都会⾃动忽略起⾸的空⽩字符。
	//%c 不忽略空⽩字符，总是返回当前第⼀个字符，⽆论该字符是否为空格。
	//char ch = 0;
	//scanf("%c", &ch);//输入   x
	//printf("===%c===\n", ch);//打印：=== ===

//如果要强制跳过字符前的空⽩字符，可以写成 scanf(" %c", &ch)，
	//即 %c 前加上⼀个空格，表⽰跳过零个或多个空⽩字符。
	//char ch = 0;
	//scanf(" %c", &ch);//输入   x
	//printf("===%c===\n", ch);//打印：===x===

//特别说⼀下scanf()中的占位符 %s ，它其实不能简单地等同于字符串。
	//它的规则是，从当前第⼀个非空⽩字符开始读起，直到遇到空⽩字符(即空格、换⾏符、制表符等)为⽌。
	//char arr[20] = "xxxxxxxxx"; //字符数组
	//scanf("%s", arr); //arr是数组名，数组名本来就是地址，故不需要加取地址符&
	//                  //输入   abc  def
	//printf("%s\n", arr);//打印：abc

//scanf()将字符串读⼊字符数组时，不会检测字符串是否超过了数组⻓度。
	//所以，储存字符串时，很可能会超过数组的边界，导致预想不到的结果。
	//为了防⽌这种情况，使⽤%s占位符时，应该指定读⼊字符串的最大长度，
	//即写成%[m]s，其中的[m]是⼀个整数，表⽰读取字符串的最⼤⻓度，后⾯的字符将被丢弃。
	//char arr[5] = {0}; //字符数组
	//scanf("%4s", arr); //%4s表示字符串能读取的最大长度为4，超过4的部分被丢弃
	//printf("%s\n", arr);

//赋值忽略符
	//int year = 0;
	//int month = 0;
	//int day = 0;
	//scanf("%d-%d-%d", &year, &month, &day);
	//printf("%d %d %d\n", year, month, day);
    //上⾯⽰例中，如果⽤户输入2020-01-01，就会正确解读出年、⽉、⽇。
	//问题是⽤⼾可能输⼊其他格式，⽐如2020/01/01，这种情况下， scanf() 解析数据就会失败。
    //为了避免这种情况， scanf() 提供了⼀个赋值忽略符 * 。
    //只要把 * 加在任何占位符的百分号后⾯，该占位符就不会返回值，解析后将被丢弃。

    //int year = 0;
    //int month = 0;
    //int day = 0;
    //scanf("%d%*c%d%*c%d", &year, &month, &day); //输入2025/1/15、2025.1.15或2025/1.15均可以
    //printf("%d %d %d\n", year, month, day);//输出均为2025 1 15
	//上⾯⽰例中，%*c就是在占位符的百分号后⾯，加入了赋值忽略符 * ，
	//表⽰这个占位符“没有对应的变量”(输入任一变量都行)，解读后不必返回。
	return 0;
}